<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>openGauss Blog  | openGauss中的最大可用模式为什么PG不做</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">

    
    <link rel="shortcut icon" href="https://xzx666.gitee.io/lookeng/img/favicon.ico" type="image/x-icon" />
    <link rel="apple-touch-icon" href="https://xzx666.gitee.io/lookeng/img/apple-touch-icon.png" />

    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

    
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
    
    <link rel="stylesheet" href="https://xzx666.gitee.io/lookeng/css/commen.css?t=1607593672000" />
    <link rel="stylesheet" href="https://xzx666.gitee.io/lookeng/css/blog.css?t=1607593672000" />
    <link rel="stylesheet" href="https://xzx666.gitee.io/lookeng/css/mobile.css?t=1607593672000" />
    <link rel="stylesheet" href="https://xzx666.gitee.io/lookeng/css/pagination.css?t=1607593672000">
    
    <script>
      var _hmt = _hmt || [];
      (function() {
        var hm = document.createElement("script");
        hm.src = "https://hm.baidu.com/hm.js?34e9f585f29581007941aa1698181871";
        var s = document.getElementsByTagName("script")[0]; 
        s.parentNode.insertBefore(hm, s);
      })();
    </script>
</head>
<body>
  <script src="//cdn1.lncld.net/static/js/3.0.4/av-min.js"></script>
  <script src='//unpkg.com/valine/dist/Valine.min.js'></script>






<div class="container">
    <div class="columns blog-detail">
        <div class="post_detail">
            <div class="is-child box">
                <div class="breadCrumb"><a href="\zh\">博客/</a></div>
                <div class="blog-detail-header">
                    <h1>openGauss中的最大可用模式为什么PG不做</h1>
                    <div class="blog-detail-prop">
                        <img src="https://xzx666.gitee.io/lookeng/img/icon-date.png">
                        <span class="article_right_date">2020-11-25</span>
                        <img src="https://xzx666.gitee.io/lookeng/img/icon-author.png">
                        <span class="article_right_author">数据库架构之美</span>
                        <img src="https://xzx666.gitee.io/lookeng/img/icon-view.png">
                        <span id="/zh/post/shujukujiagouzhimei/opengauss%E4%B8%AD%E7%9A%84%E6%9C%80%E5%A4%A7%E5%8F%AF%E7%94%A8%E6%A8%A1%E5%BC%8F%E4%B8%BA%E4%BB%80%E4%B9%88pg%E4%B8%8D%E5%81%9A/" class="leancloud_visitors" data-flag-title="openGauss中的最大可用模式为什么PG不做">
                            <i class="leancloud-visitors-count"></i>                     
                        </span>
                    </div>
                    <div class="blog-detail-tags">
                        <img src="https://xzx666.gitee.io/lookeng/img/icon-tag.png">
                        
                        <a href="https://xzx666.gitee.io/lookeng/zh/tags/opengauss%E4%B8%8Epg%E5%AF%B9%E6%AF%94">openGauss与PG对比</a>
                        
                    </div>
                </div>
                <div class="content blog-content">
                    

<h1 id="opengauss中的最大可用模式为什么pg不做-a-name-zh-cn-topic-0293240561-a">openGauss中的最大可用模式为什么PG不做<a name="ZH-CN_TOPIC_0293240561"></a></h1>

<p>pg有个一直遭人诟病的地方就是主备同步模式不能自动降级，这样会造成在同步模式下备库故障会影响主库的可用性。其实主流商业数据库如oracle、mysql等都支持在同步模式备库异常时自动进行降级，不影响或者短暂影响主库可用性。</p>

<p>至于pg为什么不做这个功能我也想了很久，下面是我自己的一点猜测。</p>

<p>pg是个追求完美主义的数据库，他从架构设计层面就会考虑如何做到完美，比如说他不用主流数据库都在使用的undo，我猜测这个原因是因为，使用undo有一个问题，undo空间不管是文件系统还是表空间都是有大小限制的，而数据库未提交的事务信息可能是无限大的，这样数据的前镜像总有可能将undo空间撑爆掉，这样就需要清理旧的undo段，如果需要查询的undo前镜像备清理了，数据库就会跑出错误，这就是oracle中经典的snapshot too old报错。所以pg摒弃了这种模式，因为他觉得必须要提供给用户一个需要的数据一定能查到的数据库，而不是本该能查到的数据被无端清理掉了，所以pg使用了多数据版本来解决这个问题，将前镜像的真实数据放在数据文件中，真正确保没有事务可能再去访问该数据时才进行清理。当然这样也带来膨胀的问题，这其实也是pg最遭人诟病的问题。</p>

<p>再来说说最大可用。pg为了追求完美，一定要确保在同步模式下切换不丢数据，这个其实保证的是：如果在pg里设置成主从同步，那么在主备failover或者备库直接promote那一刻主备的数据是完全一致的，这个我觉得是pg想保证的东西，因为既然说是同步模式，那么不丢数据是基本要求。那么再来看看最大可用有什么问题。最大可用模式的解释是：在主备连接正常情况下，主备之间以同步模式提交数据，当主备之间遭遇异常导致主备连接失败那么会自动切为异步模式，不影响主机可用性。</p>

<p>这里其实有两个问题，第一个是虽然设置了同步模式，但是不能保证切换那一刻主备数据是完全一致的，试想如果某个时间点主备之间网络发生闪断或者波动，这时很短地切为了异步模式，这时候主库依旧在写入数据，备库此时依旧同步不到了，如果这时候发生了切换，备机提升后数据相比主库是少的。这种情况的概率很低，但是有可能发生。所以我猜测pg的考虑是将低概率事件也进行消灭，给用户确切的保证，追求完美。另外一点是最大可用需要有超时窗口，这样其实是在给用户一个选择，让用户去决定我有多大事件的可用性容忍度，如果超过这个容忍度，那么我宁愿冒着可能的数据丢失风险也要进行切换保证可用性。这个参数其实是必须的，目前openGauss虽然做了最大可用，但是缺乏这个参数，主备降级很快，目前测试应该是1s以内完成切换，这个其实不合理，超时参数的需求已经提交给华为。</p>

<p>总体上我觉得最大可用模式还是利大于弊，如果没有最大可用，那么我们需要额外开发监控体系监控备机的可用性，在备机异常时触发降级。这样其实很不友好，还是希望pg将这个功能尽快实现。</p>

                </div>
            </div>
            <div class="box" style="margin-top:15px;">
                <div style="font-size:14px;color:gray"><strong>【免责声明】</strong>本文仅代表作者本人观点，与本网站无关。本网站对文中陈述、观点判断保持中立，不对所包含内容的准确性、可靠性或完整性提供任何明示或暗示的保证。本文仅供读者参考，由此产生的所有法律责任均由读者本人承担。</div>
            </div>
            <div class="post-comment">
                
                  
  <link rel="stylesheet" href="https://xzx666.gitee.io/lookeng/css/custom.css" />
  <div id="vcomments" lang="zh-cn" mess="说点什么吧..."></div>

  <script type="text/javascript">
    const placeholder = document.getElementById("vcomments").getAttribute("mess"),
          lang = document.getElementById("vcomments").getAttribute("lang");
    const  langs = lang == "zh-cn" ? "zh-cn" : "en";
    new Valine({
        el: '#vcomments' ,
        appId: '6wfgavgIRqmpC3hjHqQVtFWF-gzGzoHsz',
        appKey: 'QRqrBDBB0p0YhrGe9IJ169ip',
        avatar:'mm', 
        placeholder: placeholder,
        visitor: true,
		    meta: ['nick','mail','link'],
        lang: langs
    });
  </script>
            </div>
        </div>
    </div>
</div>
<script>
    $(function (){
        var query = new AV.Query('Counter');
        query.equalTo('url', decodeURIComponent('\/zh\/post\/shujukujiagouzhimei\/opengauss%E4%B8%AD%E7%9A%84%E6%9C%80%E5%A4%A7%E5%8F%AF%E7%94%A8%E6%A8%A1%E5%BC%8F%E4%B8%BA%E4%BB%80%E4%B9%88pg%E4%B8%8D%E5%81%9A\/'));
        query.find().then(function (data) {
            if(data.length && (data[0].attributes.author === 'openGauss')){
                var counter = AV.Object.createWithoutData('Counter', data[0].id);
                counter.set('author', '数据库架构之美');
                counter.save();
            }
        })
    })
</script>







<input id="iframeUrl" type="text" style="display: none;" value=https://xzx666.gitee.io/>




<script defer src="https://xzx666.gitee.io/lookengjs/all.js"></script>
<script src="https://xzx666.gitee.io/lookengjs/flexible.js"></script>
<script>
  const hash = window.location.search,
        pageurl = window.location.href;
  var langss = document.querySelector("html").lang === "zh-cn" ? "zh" : "en";
  console.log("hash:",hash,"pageurl:",pageurl,"ttr",pageurl.split(langss + "/")[1])

  if(!document.getElementById("vcomments")) {
    new Valine({
        appId: '6wfgavgIRqmpC3hjHqQVtFWF-gzGzoHsz',
        appKey: 'QRqrBDBB0p0YhrGe9IJ169ip',
        avatar:'mm',
        visitor: true,
		    meta: ['nick','mail','link']
    });
  }
 
  
    


    const url = document.getElementById("iframeUrl").value;

    function observe (el, options, callback) {
      var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver
      var observer = new MutationObserver(callback)
      observer.observe(el, options)
    }

    var options = {
        childList: true,
        subtree: true,
        characterData: true
      }
    observe(document.body, options, (records, instance) => {
    const height = document.body.scrollHeight;
    parent.postMessage(height,url);
    })
    if(pageurl.split(langss + "/")[1]) parent.postMessage(pageurl.split(langss + "/")[1],url);
    

    if(document.querySelector("#notFound")) parent.postMessage("我404了",url);

</script>
</body>
</html>
